/**
* @File:w25qxx_example.c
* @Version:V1.0
* @Author:rudius
* @Brief: W25QXX SPI Flash Test Program
* @Logs:
* 	Date		Author		Notes
* 	2025-07-02	rudius		First version
*/

// <<< Use Configuration Wizard in Context Menu >>>

/* Private includes --------------------------------------------------------- */
#include "w25qxx.h"
#include <rtthread.h>
#include <string.h>

#ifdef __cplusplus
extern "C" {
#endif

/* Private config ----------------------------------------------------------- */
#define TEST_SECTOR_ADDR    0x000000  // 测试扇区地址
#define TEST_DATA_SIZE      256       // 测试数据大小
#define TEST_TIMEOUT_MS     5000      // 操作超时时间

/* Private defines ---------------------------------------------------------- */
/* Private typedef ---------------------------------------------------------- */
/* Private variables -------------------------------------------------------- */
static uint8_t write_buffer[TEST_DATA_SIZE];
static uint8_t read_buffer[TEST_DATA_SIZE];
static w25qxx_device_t *w25q_dev = RT_NULL;

/* Private function prototypes ---------------------------------------------- */
static void w25qxx_test_thread_entry(void *parameter);

/*----------------------------------------------------------------------------*/
/* Private functions -------------------------------------------------------- */

/**
 * @brief 初始化测试数据
 */
static void init_test_data(void)
{
    for (int i = 0; i < TEST_DATA_SIZE; i++) {
        write_buffer[i] = i & 0xFF;
    }
}

/**
 * @brief 验证数据
 */
static bool verify_data(void)
{
    return (memcmp(write_buffer, read_buffer, TEST_DATA_SIZE) == 0);
}

/**
 * @brief W25QXX测试线程
 */
static void w25qxx_test_thread_entry(void *parameter)
{
    rt_kprintf("\n--- Starting W25QXX Test ---\n");
    
    // 1. 初始化测试数据
    init_test_data();
    rt_kprintf("Test data initialized\n");
    
    // 2. 初始化设备
    if (w25qxx_init_device(w25q_dev) != W25QXX_OK) {
        rt_kprintf("Device init failed!\n");
        return;
    }
    rt_kprintf("Device initialized\n");

    // 3. 查找设备
    w25q_dev = w25qxx_find("w25q128");
    if (!w25q_dev) {
        rt_kprintf("Device not found!\n");
        return;
    }
    rt_kprintf("Device found: %s\n", w25q_dev->name);
    
    // 4. 读取ID
    uint8_t manuf_id;
    uint16_t device_id;
    if (w25qxx_read_id(w25q_dev, &manuf_id, &device_id) == W25QXX_OK) {
        rt_kprintf("Manufacturer ID: 0x%02X, Device ID: 0x%04X\n", manuf_id, device_id);
    } else {
        rt_kprintf("Read ID failed!\n");
    }
    
    // 5. 擦除测试扇区
    rt_kprintf("Erasing sector at 0x%06X...\n", TEST_SECTOR_ADDR);
    if (w25qxx_erase_sector(w25q_dev, TEST_SECTOR_ADDR) != W25QXX_OK) {
        rt_kprintf("Sector erase failed!\n");
        return;
    }
    
    // 6. 等待擦除完成
    if (w25qxx_wait_busy(w25q_dev, TEST_TIMEOUT_MS) != W25QXX_OK) {
        rt_kprintf("Erase timeout!\n");
        return;
    }
    rt_kprintf("Sector erased\n");
    
    // 7. 写入数据
    rt_kprintf("Writing %d bytes...\n", TEST_DATA_SIZE);
    if (w25qxx_page_program(w25q_dev, TEST_SECTOR_ADDR, write_buffer, TEST_DATA_SIZE) != W25QXX_OK) {
        rt_kprintf("Write failed!\n");
        return;
    }
    
    // 8. 等待写入完成
    if (w25qxx_wait_busy(w25q_dev, TEST_TIMEOUT_MS) != W25QXX_OK) {
        rt_kprintf("Write timeout!\n");
        return;
    }
    rt_kprintf("Data written\n");
    
    // 9. 读取数据
    rt_kprintf("Reading data...\n");
    if (w25qxx_read_data(w25q_dev, TEST_SECTOR_ADDR, read_buffer, TEST_DATA_SIZE) != W25QXX_OK) {
        rt_kprintf("Read failed!\n");
        return;
    }
    
    // 10. 验证数据
    if (verify_data()) {
        rt_kprintf("Data verification SUCCESS!\n");
    } else {
        rt_kprintf("Data verification FAILED!\n");
        
        // 打印前16字节对比
        rt_kprintf("First 16 bytes comparison:\n");
        rt_kprintf("Written: ");
        for (int i = 0; i < 16; i++) rt_kprintf("%02X ", write_buffer[i]);
        rt_kprintf("\nRead   : ");
        for (int i = 0; i < 16; i++) rt_kprintf("%02X ", read_buffer[i]);
        rt_kprintf("\n");
    }
    
    rt_kprintf("--- Test Completed ---\n\n");
}

/* Public functions --------------------------------------------------------- */

/**
 * @brief 初始化测试示例
 */
int w25qxx_example_init(void)
{
    rt_thread_t tid;
    
    // 创建测试线程
    tid = rt_thread_create("w25q_test",
                           w25qxx_test_thread_entry,
                           RT_NULL,
                           2048,
                           RT_THREAD_PRIORITY_MAX / 2,
                           20);
    if (tid != RT_NULL) {
        rt_thread_startup(tid);
        return RT_EOK;
    }
    
    return -RT_ENOMEM;
}
MSH_CMD_EXPORT(w25qxx_example_init, W25QXX SPI Flash Test Example);
#ifdef __cplusplus
}
#endif
// <<< end of configuration section >>>
/* ----------------------------- end of w251xx_example.c ---------------------------- */